import threading
from threading import main_thread, Thread
#coding UTF-8
import self
import wx
import time
from socket import socket,AF_INET,SOCK_STREAM

class YsjServer(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,id=1002,title='某工作室界面')
        # 创建面板对象
        pl = wx.Panel(self)
        # 面板中放盒子
        box = wx.BoxSizer(wx.VERTICAL)
        # 可伸缩的网格布局
        fgz1 = wx.FlexGridSizer(wx.HSCROLL)

        start_server_btn = wx.Button(parent=pl, size=(133,40), label='启动')
        record_btn = wx.Button(parent=pl, size=(133, 40), label='保存聊天记录')
        stop_server_btn = wx.Button(parent=pl, size=(133, 40), label='离开')

        fgz1.Add(start_server_btn, 1, wx.TOP)
        fgz1.Add(record_btn, 1, wx.TOP )
        fgz1.Add(stop_server_btn, 1, wx.TOP)
        # (可伸缩的网络布局)添加到box中
        box.Add(fgz1, 1, wx.ALIGN_CENTRE)

        # 只读文本框
        self.show_text = wx.TextCtrl(pl, size=(400, 410), style=wx.TE_MULTILINE | wx.TE_READONLY)
        box.Add(self.show_text, 1, wx.ALIGN_CENTRE)

        #盒子放面板
        pl.SetSizer(box)



        '--------界面绘制--------'
        '-----------服务器功能------'
        self.isOn=False
        self.host_port=('',8888)
        # 创建socket对象
        self.server_socket = socket(AF_INET, SOCK_STREAM)
        # 绑定IP地址和端口
        self.server_socket.bind(self.host_port)
        # 监听
        self.server_socket.listen(5)
        # 创建一个字典，存储与客户端对话的会话线程
        self.session_thread_dict = {}  # key-value {客户端的名称key:会话线程value}

        # 当鼠标点击“启动服务”按钮时，要执行的操作
        self.Bind(wx.EVT_BUTTON,self.start_server,start_server_btn)
        #'保存聊天记录'
        self.Bind(wx.EVT_BUTTON, self.save_record,record_btn )
        # '断开'
        self.Bind(wx.EVT_BUTTON, self.stop_server, stop_server_btn)

    def stop_server(self, event):
        print('服务器已停止服务')
        self.isOn = False

    def save_record(self, event):
        record_data = self.show_text.GetValue()
        with open('record.log', 'w', encoding='utf-8') as file:
            file.write(record_data)

    def start_server(self,event):
        #判断是否启动
        if not self.isOn:
            #启动
            self.isOn=True
            #创建主线程对象
            main_thread=threading.Thread(target=self.do_work())
            #设置守护线程，父线程执行结束，子线程也自动关闭
            main_thread.demon=True

            #启动
            main_thread.start()

    def do_work(self):
         while self.isOn:
             #接收客户端的连接请求
            session_socket,client_addr=self.server_socket.accept()
            #客户端发送连接请求之后，发送过来的第一条数据为客户端的名称，作为键
            user_name=session_socket.recv(1024).decode('utf-8')
            #创建绘画线程对象
            session_thread=SessionThread(session_socket,user_name,self)
            self.session_thread_dict[user_name]=session_thread
            session_thread.start()
            self.show_info_and_send_client('服务器通知', f'欢迎{user_name}进入聊天室！',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
                                           )

         self.server_socket.close()

    def show_info_and_send_client(self, data_source, data, date_time):
        # 字符串操作
        send_data = f'{data_source}:{data}\n时间:{date_time}'
        # 只读文本框
        self.show_text.AppendText('-' * 40 + '\n' + send_data + '\n')
        # 给每一个客户端都发送一次
        for client in self.session_thread_dict.values():
            # 如果当前的会话处于开启状态
            if client.isOn:
                client.client_socket.send(send_data.encode('utf-8'))


class SessionThread(threading.Thread):
    def __init__(self,client_socket,user_name,server):
        # 调用父类的初始化方法
        threading.Thread.__init__(self)
        self.client_socket = client_socket
        self.user_name = user_name
        self.server = server
        self.isOn = True  # 会话线程是否启动，当创建SessionThread对象时会话线程即启动

    def run(self) -> None:
        print(f'客户端:{self.user_name}已经和服务器连接成功，服务器启动一个会话线程')
        while self.isOn:
            # 从客户端接收数据 存储到data中
            data = self.client_socket.recv(1024).decode('utf-8')
            # 如果客户端点击断开按钮，先给服务器发送一句话， 消息自定义  Y-disconnect-SJ 自定义的结束词儿
            if data == 'Y-disconnect-SJ':
                self.isOn = False
                self.server.show_info_and_send_client('服务器通知',f'{self.user_name}离开聊天室',
                                                      time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))

            else:
                # 其它聊天信息显示给所有的客户端，包含服务器也显示
                # 调用刚才编写的方法
                self.server.show_info_and_send_client(self.user_name, data,time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        # 关闭 socket
        self.client_socket.close()
if __name__ == '__main__':
    app=wx.App()
    server =YsjServer()
    server.Show()
    app.MainLoop()